package org.awa.demo.opencv.gis;

import lombok.extern.slf4j.Slf4j;
import org.geotools.data.FeatureWriter;
import org.geotools.data.Transaction;
import org.geotools.data.store.ContentFeatureCollection;
import org.geotools.data.store.ContentFeatureSource;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.geojson.geom.GeometryJSON;
import org.geotools.geometry.jts.JTS;
import org.geotools.referencing.CRS;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.locationtech.jts.geom.*;
import org.locationtech.jts.io.ParseException;
import org.locationtech.jts.io.WKTReader;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;
import org.springframework.stereotype.Component;

import java.io.*;
import java.lang.reflect.Field;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author xxf
 */
@Slf4j
@Component
public class GeoToolsUtils {

    /*
     * 因为地球为椭圆，根据墨卡托计算后计算结果会偏大，所以需要与真实值之间计算修正系数，套用到计算结果
     *
     * double rate = Math.cos(Math.toRadians(point84.getCoordinate().y));//短距离
     * double rate = Math.cos((Math.toRadians(k96.y) + Math.toRadians(k97.y)) / 2.000000);//长距离
     */
    private final double RATE = 0.8482973000510488d;

    /**
     *  WKT 格式转化为 GeoJson
     * @Param: 传入WKT形式的字符串
     */

    public String WktToGeojson(String wktPoint){
        WKTReader reader = new WKTReader();
        Geometry geometry = null;
        try {
            geometry = reader.read(wktPoint);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        StringWriter writer = new StringWriter();
        GeometryJSON g = new GeometryJSON();
        try {
            g.write(geometry, writer);
        } catch (IOException e) {
            e.printStackTrace();
        }
        String result = writer.toString();
        return result;
    }

    /**
     *  GeoJson 格式转化为 WKT
     * @Param: 传入GeoJson形式的字符串
     */
    public String GeojsonToWkt(String geoJson) {
        GeometryJSON gjson = new GeometryJSON();
        Reader reader = new StringReader(geoJson);
        Geometry geometry = null;
        try {
            geometry = gjson.read(reader);
        } catch (IOException e) {
            e.printStackTrace();
        }
        String wkt = geometry.toText();
        return wkt;
    }


    /**
     * 点线之间算距离
     *
     * @param pointWKT
     * @param lineWKT
     * @return
     * @throws Exception
     */
    public double getDistanceWithPointAndLine(String pointWKT,String lineWKT) throws Exception{
        // WGS84(一般项目中常用的是CRS:84和EPSG:4326)  EPSG:4326：WGS84坐标系，GPS坐标系。EPSG 4490：CGCS2000坐标系，大地坐标系
        CoordinateReferenceSystem sourceCRS = CRS.decode("CRS:84");
        // Pseudo-Mercator(墨卡托投影)
        CoordinateReferenceSystem targetCRS = CRS.decode("EPSG:3857");
        //坐标转换算法
        MathTransform transform = CRS.findMathTransform(sourceCRS, targetCRS, false);
        //获取WGS84坐标系的经纬度
        GeometryFactory geometryFactory = new GeometryFactory();
        WKTReader reader = new WKTReader(geometryFactory);

        //转换为墨卡托坐标系的几何图形
        Geometry lineMercator = JTS.transform(reader.read(lineWKT), transform);
        Geometry pointMercator = JTS.transform(reader.read(pointWKT), transform);

        //计算距离
        return pointMercator.distance(lineMercator) * RATE;
    }

    /**
     * 点点之间算距离
     *
     * @param pointWKT1
     * @param pointWKT2
     * @return
     * @throws Exception
     */
    public double getDistanceWithPointAndPoint(String pointWKT1,String pointWKT2) throws Exception{
        // WGS84(一般项目中常用的是CRS:84和EPSG:4326)
        CoordinateReferenceSystem sourceCRS = CRS.decode("CRS:84");
        // Pseudo-Mercator(墨卡托投影)
        CoordinateReferenceSystem targetCRS = CRS.decode("EPSG:3857");
        //坐标转换算法
        MathTransform transform = CRS.findMathTransform(sourceCRS, targetCRS, false);
        //获取WGS84坐标系的经纬度
        GeometryFactory geometryFactory = new GeometryFactory();
        WKTReader reader = new WKTReader(geometryFactory);
        //转换为墨卡托坐标系的几何图形
        Geometry pointMercator1 = JTS.transform(reader.read(pointWKT1), transform);
        Geometry pointMercator2 = JTS.transform(reader.read(pointWKT2), transform);

        //计算距离
        return pointMercator1.distance(pointMercator2) * RATE;
    }

    /**
     * 算多边形周长
     *
     * @param polygonWKT
     * @return
     * @throws Exception
     */
    public double getLengthWithPolygon(String polygonWKT) throws Exception{
        // WGS84(一般项目中常用的是CRS:84和EPSG:4326)
        CoordinateReferenceSystem sourceCRS = CRS.decode("CRS:84");
        // Pseudo-Mercator(墨卡托投影)
        CoordinateReferenceSystem targetCRS = CRS.decode("EPSG:3857");
        //坐标转换算法
        MathTransform transform = CRS.findMathTransform(sourceCRS, targetCRS, false);
        //获取WGS84坐标系的经纬度
        GeometryFactory geometryFactory = new GeometryFactory();
        WKTReader reader = new WKTReader(geometryFactory);
        Polygon polygon84 = (Polygon) reader.read(polygonWKT);

        //转换为墨卡托坐标系的几何图形
        Geometry polygonMercator = JTS.transform(polygon84, transform);

        //计算距离
        return polygonMercator.getLength() * RATE;
    }
}
